package zhjb.temp.db;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import zhjb.temp.db.annotation.Id;

/**
 * mysql的dao
 * 
 * @author zhangjianbing@msn.com
 * 
 */
public class MySQL implements Dao {
	public void add(Object obj, Connection conn) throws Exception {
		Class clazz = obj.getClass();
		VTable table = Context.getVTable(clazz);
		Map<String, VField> map = table.getMap();
		StringBuilder sbSQL = new StringBuilder();
		StringBuilder sbPre = new StringBuilder();
		List<VField> list = new ArrayList<VField>();
		for (Map.Entry<String, VField> entry : map.entrySet()) {
			if (sbSQL.length() > 0) {
				sbSQL.append(",");
			}
			sbSQL.append(entry.getKey());
			if (sbPre.length() > 0) {
				sbPre.append(",");
			}
			sbPre.append("?");
			list.add(entry.getValue());
		}
		sbSQL.insert(0, "insert into " + table.getName() + "(");
		sbSQL.append(") values (").append(sbPre).append(")");
		System.out.println(sbSQL);
		PreparedStatement pst = conn.prepareStatement(sbSQL.toString());
		int i = 0;
		for (VField f : list) {
			i++;
			Method method = f.getGetMethod();
			Object value = null;
			if (method.getAnnotation(Id.class) != null) {
				value = UUID.randomUUID().toString().replace("-", "");
			} else {
				value = method.invoke(obj);
			}
			pst.setObject(i, value);
		}
		try {
			pst.execute();
		} catch (Exception e) {
			throw e;
		}
		pst.close();
	}

	/**
	 * 根据主键查找一条数据
	 */
	public Object getByPK(String pk, Class clazz, Connection conn) throws Exception {
		VTable table = Context.getVTable(clazz);
		StringBuilder sbSQL = new StringBuilder();
		Map<String, VField> map = table.getMap();
		for (Map.Entry<String, VField> entry : map.entrySet()) {
			if (sbSQL.length() > 0) {
				sbSQL.append(",");
			}
			sbSQL.append(entry.getKey());
		}
		sbSQL.insert(0, "select ").append(" from ").append(table.getName()).append(" where ").append(table.getIdName()).append("=?");
		PreparedStatement pst = conn.prepareStatement(sbSQL.toString());
		pst.setString(1, pk);
		ResultSet rs = pst.executeQuery();
		List<Map<String, Object>> dbresult = fix(rs, map);
		rs.close();
		pst.close();
		if (dbresult != null && !dbresult.isEmpty()) {
			return fixObject(dbresult.get(0), clazz, map);
		}
		return null;
	}

	/**
	 * 拼装成一个对象
	 * 
	 * @param map
	 * @param clazz
	 * @return
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 * @throws InvocationTargetException
	 * @throws IllegalArgumentException
	 */
	private Object fixObject(Map<String, Object> map, Class<? extends Object> clazz, Map<String, VField> fieldMap) throws InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
		Object obj = clazz.newInstance();
		for (Map.Entry<String, Object> entry : map.entrySet()) {
			Object value = entry.getValue();
			VField field = fieldMap.get(entry.getKey());
			Method setMethod = field.getSetMethod();
			setMethod.invoke(obj, value);
		}
		return obj;
	}

	/**
	 * 从数据库中获取数据
	 * 
	 * @param rs
	 * @param map
	 * @return
	 * @throws SQLException
	 */
	private List<Map<String, Object>> fix(ResultSet rs, Map<String, VField> map) throws SQLException {
		Map<String, Object> valueMap = new HashMap<String, Object>();
		ResultSetMetaData rsmd = rs.getMetaData();
		int count = rsmd.getColumnCount();
		String[] columns = new String[count];
		for (int i = 1; i <= count; i++) {
			columns[i - 1] = rsmd.getColumnName(i);
		}
		while (rs.next()) {
			for (String c : columns) {
				VField field = map.get(c);
				Object value = null;
				if (field.getType() == VType.STRING || field.getType() == VType.CHAR) {
					value = rs.getString(c);
				} else if (field.getType() == VType.BOOLEAN) {
					value = rs.getBoolean(c);
				} else if (field.getType() == VType.DATE) {
					value = rs.getTimestamp(c);
				} else if (field.getType() == VType.INT) {
					value = rs.getInt(c);
				} else if (field.getType() == VType.DOUBLE) {
					value = rs.getDouble(c);
				} else if (field.getType() == VType.FLOAT) {
					value = rs.getFloat(c);
				} else if (field.getType() == VType.LONG) {
					value = rs.getLong(c);
				} else if (field.getType() == VType.SHORT) {
					value = rs.getShort(c);
				}
				valueMap.put(c, value);
			}
		}
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		result.add(valueMap);
		return result;
	}
}
